home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 4
/
Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso
/
Pearls
/
disk
/
Devs+Handler
/
Flat-Handler
/
Flat-Handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-05
|
48KB
|
1,894 lines
;/*
SC NMINC MCCONS STREQ NOWVRET STRMERGE NOSTKCHK OPTTIME IGNORE=73 Flat-Handler.c
SLINK Flat-Handler.o TO Flat-Handler LIB LIB:sc.lib LIB:amiga.lib SC SD ND
Protect Flat-Handler -e
Copy Flat-Handler L:
Quit
*/
#include <intuition/intuitionbase.h>
#include <libraries/filehandler.h>
#include <libraries/dosextens.h>
#include <devices/trackdisk.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <clib/intuition_protos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <stdarg.h>
#include <string.h>
#define DB(x) ;
/* Standard FS error types. */
enum { ERR_WRITEPROTECT,ERR_NODISK,ERR_UNREADABLE,ERR_WRITEERROR };
/* This is a link node used both for locks and filehandles. */
struct FlatNode
{
struct FlatNode *fn_Succ; /* Vanilla node head. */
struct FlatNode *fn_Pred;
ULONG fn_UniqueID; /* A unique ID. */
LONG fn_Mode; /* Either shared or exclusive. */
struct DeviceNode *fn_DevInfo; /* Pointer to a device node,
* needed by ExNext and the like.
*/
ULONG fn_BlockSize; /* Size of a block (512 bytes are standard). */
ULONG fn_FirstBlock; /* The first accessible block. */
ULONG fn_NumBlocks; /* Maximum number of available blocks. */
LONG fn_Position; /* Current file position in bytes. */
struct FileLock fn_Lock; /* A dummy file lock. */
UBYTE fn_Name[40]; /* Name of this file. */
struct IOExtTD *fn_DiskRequest;
APTR fn_DiskBuffer;
BYTE fn_CheckCount; /* The disk state is checked
* every tenth r/w attempt,
* this byte keeps the count.
*/
};
/* This list keeps all the locks and filehandles. */
struct List FlatList;
/* Each open/lock call increments this counter to
* guarantee that each item receives a unique identifier.
*/
ULONG UniqueCounter = 0;
/* Shared library identifiers. */
struct ExecBase *SysBase = NULL;
struct DosLibrary *DOSBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
/* Prototypes for this module. */
LONG __saveds HandlerEntry(VOID);
LONG __regargs DoRead(struct FlatNode *FlatNode,LONG *Error,LONG Size,UBYTE *Buffer,struct Process *Caller);
LONG __regargs DoWrite(struct FlatNode *FlatNode,LONG *Error,LONG Size,UBYTE *Buffer,struct Process *Caller);
UBYTE * __regargs BaseName(UBYTE *String);
UBYTE __regargs Local2Upper(UBYTE c);
UBYTE __regargs StrCmp(UBYTE *a,UBYTE *b);
struct FlatNode * __regargs FindFlatNodeByID(ULONG UniqueID);
struct FlatNode * __regargs FindFlatNodeByName(UBYTE *Name);
VOID __regargs BtoCStr(UBYTE *Name,BSTR String,LONG MaxLength);
LONG __regargs ShowRequest(APTR WindowPtr,BYTE Type,UBYTE *Drive);
struct DeviceNode * __regargs FindDevice(struct DeviceNode *LastNode,struct FileSysStartupMsg **Startup,struct DosEnvec **DosEnvec,UBYTE *Name);
VOID __regargs DeleteNode(struct FlatNode *FlatNode);
struct FlatNode * __regargs CreateNode(struct MsgPort *DiskPort,LONG Type,UBYTE *Name);
VOID __regargs ReturnPacket(struct DosPacket *Packet,ULONG Res1,ULONG Res2,struct Process *HandlerProc);
struct DosPacket * __regargs WaitPacket(struct Process *HandlerProc);
/* HandlerEntry():
*
* Entry point for this module.
*/
LONG __saveds
HandlerEntry()
{
struct Process *HandlerProc;
struct FileHandle *FileHandle;
struct FileLock *FileLock;
LONG ReadBytes,WriteBytes,Bytes;
LONG NewPosition;
struct FileInfoBlock *FileInfo;
struct InfoData *InfoData;
UBYTE *FileName;
UBYTE NameBuffer[257];
struct DosPacket *FlatPacket;
struct DeviceNode *FlatDevNode;
struct DeviceList *VolumeNode;
struct FlatNode *FlatNode;
struct MsgPort *DiskPort;
struct DateStamp CreationDate;
UBYTE __aligned VolumeName[264];
/* Set up SysBase. */
SysBase = *(struct ExecBase **)4;
/* Know who we are. */
HandlerProc = (struct Process *)SysBase -> ThisTask;
/* Started from Shell (oops!)? */
if(!HandlerProc -> pr_CLI)
{
/* Wait for startup packet. */
FlatPacket = WaitPacket(HandlerProc);
/* Clear the list. */
NewList(&FlatList);
/* Pick up the pointer to our DeviceNode. */
FlatDevNode = (struct DeviceNode *)BADDR(FlatPacket -> dp_Arg3);
/* Install ourselves at the other hand. */
FlatDevNode -> dn_Task = &HandlerProc -> pr_MsgPort;
if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",0)))
{
ReturnPacket(FlatPacket,DOSFALSE,FlatPacket -> dp_Res2,HandlerProc);
goto FallOff;
}
DateStamp(&CreationDate);
/* Open Intuition; we might want to put up
* auto-requesters.
*/
if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)))
{
ReturnPacket(FlatPacket,DOSFALSE,FlatPacket -> dp_Res2,HandlerProc);
goto FallOff;
}
if(!(DiskPort = CreatePort(NULL,0)))
{
ReturnPacket(FlatPacket,DOSFALSE,FlatPacket -> dp_Res2,HandlerProc);
goto FallOff;
}
if(!(VolumeNode = (struct DeviceList *)AllocMem(sizeof(struct DeviceList),MEMF_ANY | MEMF_CLEAR)))
{
ReturnPacket(FlatPacket,DOSFALSE,FlatPacket -> dp_Res2,HandlerProc);
goto FallOff;
}
FileName = VolumeName;
*(ULONG *)FileName = 264;
FileName += 4;
strcpy(FileName,"\7Devices");
VolumeNode -> dl_Type = DLT_VOLUME;
VolumeNode -> dl_Task = &HandlerProc -> pr_MsgPort;
VolumeNode -> dl_DiskType = ID_DOS_DISK;
VolumeNode -> dl_Name = MKBADDR(FileName);
VolumeNode -> dl_VolumeDate = CreationDate;
Forbid();
// I removed the following lines because i only use flat for AMAX
VolumeNode -> dl_Next = ((struct DosInfo *)BADDR(((struct RootNode *)DOSBase -> dl_Root) -> rn_Info)) -> di_DevInfo;
((struct DosInfo *)BADDR(((struct RootNode *)DOSBase -> dl_Root) -> rn_Info)) -> di_DevInfo = MKBADDR(VolumeNode);
Permit();
/* Initialization finished, now return the
* startup packet.
*/
ReturnPacket(FlatPacket,DOSTRUE,FlatPacket -> dp_Res2,HandlerProc);
/* Go into loop waiting for data packets. */
FOREVER
{
/* Wait for packet. */
FlatPacket = WaitPacket(HandlerProc);
DB(kprintf("Packet from \"%s\"\n",((struct Task *)FlatPacket -> dp_Port -> mp_SigTask) -> tc_Node . ln_Name));
/* Examine the packet type. */
switch(FlatPacket -> dp_Type)
{
case ACTION_RENAME_DISK:
DB(kprintf("ACTION_RENAME_DISK\n"));
if(FlatPacket -> dp_Arg1)
{
UBYTE *NewName = (UBYTE *)BADDR(FlatPacket -> dp_Arg1);
if(NewName[0])
{
LONG Len = *NewName++;
if(Len > 256)
Len = 256;
FileName = VolumeName + 4;
Forbid();
*FileName++ = Len;
memcpy(FileName,NewName,Len);
FileName[Len] = 0;
Permit();
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_INVALID_COMPONENT_NAME,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_INVALID_COMPONENT_NAME,HandlerProc);
break;
case ACTION_PARENT:
DB(kprintf("ACTION_PARENT\n"));
if(FlatPacket -> dp_Arg1)
{
if(FlatNode = FindFlatNodeByID(((struct FileLock *)BADDR(FlatPacket -> dp_Arg1)) -> fl_Key))
{
if(FlatNode -> fn_Name[1])
{
if(FlatNode = CreateNode(DiskPort,SHARED_LOCK,NULL))
{
AddTail(&FlatList,(struct Node *)FlatNode);
FlatNode -> fn_Lock . fl_Access = SHARED_LOCK;
FlatNode -> fn_Lock . fl_Task = &HandlerProc -> pr_MsgPort;
FlatNode -> fn_Lock . fl_Volume = MKBADDR(VolumeNode);
FlatNode -> fn_Lock . fl_Key = FlatNode -> fn_UniqueID;
ReturnPacket(FlatPacket,MKBADDR(&FlatNode -> fn_Lock),NULL,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
}
else
ReturnPacket(FlatPacket,0,0,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
}
else
ReturnPacket(FlatPacket,0,0,HandlerProc);
break;
case ACTION_INFO:
DB(kprintf("ACTION_INFO\n"));
if(InfoData = (struct InfoData *)BADDR(FlatPacket -> dp_Arg2))
{
memset(InfoData,0,sizeof(struct InfoData));
InfoData -> id_DiskState = ID_VALIDATED;
InfoData -> id_NumBlocks = 2;
InfoData -> id_NumBlocksUsed = 2;
InfoData -> id_BytesPerBlock = 512;
InfoData -> id_DiskType = ID_DOS_DISK;
InfoData -> id_VolumeNode = MKBADDR(VolumeNode);
InfoData -> id_InUse = DOSTRUE;
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
break;
case ACTION_DISK_INFO:
DB(kprintf("ACTION_DISK_INFO\n"));
if(InfoData = (struct InfoData *)BADDR(FlatPacket -> dp_Arg1))
{
memset(InfoData,0,sizeof(struct InfoData));
InfoData -> id_DiskState = ID_VALIDATED;
InfoData -> id_NumBlocks = 2;
InfoData -> id_NumBlocksUsed = 2;
InfoData -> id_BytesPerBlock = 512;
InfoData -> id_DiskType = ID_DOS_DISK;
InfoData -> id_VolumeNode = MKBADDR(VolumeNode);
InfoData -> id_InUse = DOSTRUE;
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
break;
case ACTION_CURRENT_VOLUME:
DB(kprintf("ACTION_CURRENT_VOLUME\n"));
ReturnPacket(FlatPacket,MKBADDR(VolumeNode),NULL,HandlerProc);
break;
case ACTION_IS_FILESYSTEM:
DB(kprintf("ACTION_IS_FILESYSTEM\n"));
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
break;
/* Obtain a filelock. */
case ACTION_LOCATE_OBJECT:
/* Convert the file name. */
BtoCStr(NameBuffer,FlatPacket -> dp_Arg2,256);
DB(kprintf("ACTION_LOCATE_OBJECT \"%s\" %ld\n",NameBuffer,FlatPacket -> dp_Arg3));
/* Are we to return a lock
* to a file or a lock to the
* root directory?
*/
if(FileName = BaseName(NameBuffer))
{
DB(kprintf("base name \"%s\"\n",FileName));
/* Look for a file of this name. */
if(FlatNode = FindFlatNodeByName(FileName))
{
/* See if the file is currently locked. */
if((FlatNode -> fn_Mode != FlatPacket -> dp_Arg3) || (FlatPacket -> dp_Arg3 == EXCLUSIVE_LOCK && FlatNode -> fn_Mode == EXCLUSIVE_LOCK))
{
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_IN_USE,HandlerProc);
break;
}
}
/* Create a new item and add it to the list. */
if(FlatNode = CreateNode(DiskPort,FlatPacket -> dp_Arg3,FileName))
{
AddTail(&FlatList,(struct Node *)FlatNode);
/* Initialize the default data so DOS will
* get along with us.
*/
FlatNode -> fn_Lock . fl_Access = FlatPacket -> dp_Arg3;
FlatNode -> fn_Lock . fl_Task = &HandlerProc -> pr_MsgPort;
FlatNode -> fn_Lock . fl_Volume = MKBADDR(VolumeNode);
FlatNode -> fn_Lock . fl_Key = FlatNode -> fn_UniqueID;
strcpy(&FlatNode -> fn_Name[1],FileName);
ReturnPacket(FlatPacket,MKBADDR(&FlatNode -> fn_Lock),NULL,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
}
else
{
if(FlatNode = CreateNode(DiskPort,FlatPacket -> dp_Arg3,NULL))
{
AddTail(&FlatList,(struct Node *)FlatNode);
FlatNode -> fn_Lock . fl_Access = FlatPacket -> dp_Arg3;
FlatNode -> fn_Lock . fl_Task = &HandlerProc -> pr_MsgPort;
FlatNode -> fn_Lock . fl_Volume = MKBADDR(VolumeNode);
FlatNode -> fn_Lock . fl_Key = FlatNode -> fn_UniqueID;
ReturnPacket(FlatPacket,MKBADDR(&FlatNode -> fn_Lock),NULL,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
}
break;
/* Free a lock obtained above. */
case ACTION_FREE_LOCK:
DB(kprintf("ACTION_FREE_LOCK\n"));
/* Is the lock part of the list? */
if(FlatPacket -> dp_Arg1)
{
if(FlatNode = FindFlatNodeByID(((struct FileLock *)BADDR(FlatPacket -> dp_Arg1)) -> fl_Key))
{
Remove((struct Node *)FlatNode);
DeleteNode(FlatNode);
}
}
ReturnPacket(FlatPacket,DOSTRUE,0,HandlerProc);
break;
/* Duplicate a shared lock. */
case ACTION_COPY_DIR:
DB(kprintf("ACTION_COPY_DIR\n"));
/* Are we to duplicate a non-ZERO lock? */
if(FlatPacket -> dp_Arg1)
{
FileLock = (struct FileLock *)BADDR(FlatPacket -> dp_Arg1);
/* Try to find the corresponding list entry. */
if(FlatNode = FindFlatNodeByID(FileLock -> fl_Key))
{
/* Only shared locks may be duplicated. */
if(FlatNode -> fn_Mode == EXCLUSIVE_LOCK)
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_IN_USE,HandlerProc);
else
{
struct FlatNode *AnotherNode;
/* Create a new node. */
if(FlatNode -> fn_Name[1])
AnotherNode = CreateNode(DiskPort,SHARED_LOCK,&FlatNode -> fn_Name[1]);
else
AnotherNode = CreateNode(DiskPort,SHARED_LOCK,NULL);
/* Did we get what we wanted? */
if(AnotherNode)
{
/* Not quite so unique I suppose. */
AnotherNode -> fn_UniqueID = FlatNode -> fn_UniqueID;
/* Add the freshly created lock
* to the list.
*/
AddTail(&FlatList,(struct Node *)AnotherNode);
/* Fill in the Lock data. */
AnotherNode -> fn_Lock . fl_Access = SHARED_LOCK;
AnotherNode -> fn_Lock . fl_Task = &HandlerProc -> pr_MsgPort;
AnotherNode -> fn_Lock . fl_Volume = MKBADDR(VolumeNode);
AnotherNode -> fn_Lock . fl_Key = AnotherNode -> fn_UniqueID;
/* Successful return. */
ReturnPacket(FlatPacket,MKBADDR(&AnotherNode -> fn_Lock),NULL,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_NO_FREE_STORE,HandlerProc);
}
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
}
else
ReturnPacket(FlatPacket,0,0,HandlerProc);
break;
/* Examine a file. */
case ACTION_EXAMINE_OBJECT:
DB(kprintf("ACTION_EXAMINE_OBJECT\n"));
/* Are both identifiers valid? */
if((FileLock = (struct FileLock *)BADDR(FlatPacket -> dp_Arg1)) && (FileInfo = (struct FileInfoBlock *)BADDR(FlatPacket -> dp_Arg2)))
{
BYTE Success = FALSE;
/* Can we find the item? */
if(FlatNode = FindFlatNodeByID(FileLock -> fl_Key))
{
DB(kprintf("name \"%s\"\n",&FlatNode -> fn_Name[1]));
/* Is it a file or a directory? */
if(FlatNode -> fn_Name[1])
{
struct FileSysStartupMsg *Startup;
struct DosEnvec *DosEnvec;
/* Find the approriate device. */
if(FlatNode -> fn_DevInfo = FindDevice(NULL,&Startup,&DosEnvec,&FlatNode -> fn_Name[1]))
{
struct IOExtTD *DiskRequest;
if(DiskRequest = (struct IOExtTD *)CreateExtIO(DiskPort,sizeof(struct IOExtTD)))
{
BtoCStr(NameBuffer,Startup -> fssm_Device,256);
if(!OpenDevice(NameBuffer,Startup -> fssm_Unit,DiskRequest,Startup -> fssm_Flags))
{
/* We are actually faking part of the data
* to be returned in the fileinfoblock.
* This isn't Unix and there are only two
* kinds of directory entries: files and
* directories. The protection bits are by
* default configured to mimic the state of
* the corresponding drive. If not write-
* enabled, the file will have the write
* access-bit cleared, if there is no disk
* in the drive, the read bit will be cleared,
* the file size will be zero as well.
*/
memset(FileInfo,0,sizeof(struct FileInfoBlock));
FileInfo -> fib_DiskKey = FileLock -> fl_Key;
FileInfo -> fib_DirEntryType = ST_FILE;
FileInfo -> fib_Protection = FIBF_EXECUTE|FIBF_DELETE;
FileInfo -> fib_Size = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces * (DosEnvec -> de_SizeBlock << 2);
FileInfo -> fib_NumBlocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
FileInfo -> fib_Date = CreationDate;
memcpy(FileInfo -> fib_FileName,BADDR(FlatNode -> fn_DevInfo -> dn_Name),((UBYTE *)BADDR(FlatNode -> fn_DevInfo -> dn_Name))[0] + 1);
DiskRequest -> iotd_Req . io_Command = TD_PROTSTATUS;
if(!DoIO(DiskRequest))
{
if(DiskRequest -> iotd_Req . io_Actual)
FileInfo -> fib_Protection |= FIBF_WRITE;
}
DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
if(!DoIO(DiskRequest))
{
if(DiskRequest -> iotd_Req . io_Actual)
{
FileInfo -> fib_Protection |= FIBF_READ|FIBF_WRITE;
FileInfo -> fib_Size = FileInfo -> fib_NumBlocks = 0;
}
}
Success = TRUE;
CloseDevice(DiskRequest);
}
DeleteExtIO(DiskRequest);
}
}
}
else
{
/* This is very much the same as above,
* but this time it's the root directory
* we will create.
*/
memset(FileInfo,0,sizeof(struct FileInfoBlock));
FileInfo -> fib_DiskKey = FileLock -> fl_Key;
FileInfo -> fib_DirEntryType = ST_ROOT;
FileInfo -> fib_Protection = FIBF_EXECUTE;
FileInfo -> fib_Size = 0;
FileInfo -> fib_NumBlocks = 0;
FileInfo -> fib_Date = CreationDate;
strcpy(FileInfo -> fib_FileName,VolumeName + 4);
Success = TRUE;
}
}
if(Success)
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
break;
/* Examine a file. */
case ACTION_EXAMINE_FH:
DB(kprintf("ACTION_EXAMINE_FH\n"));
/* Both FIB buffer && FileHandle valid? */
if(FileInfo = (struct FileInfoBlock *)BADDR(FlatPacket -> dp_Arg2))
{
BYTE Success = FALSE;
DB(kprintf("FileInfo: %08lx, NodeID: %ld \n",FileInfo,FlatPacket -> dp_Arg1));
/* Can we find the item? */
if(FlatNode = FindFlatNodeByID(FlatPacket -> dp_Arg1))
{
struct FileSysStartupMsg *Startup;
struct DosEnvec *DosEnvec;
DB(kprintf("name \"%s\"\n",&FlatNode -> fn_Name[1]));
/* Find the approriate device. */
if(FlatNode -> fn_DevInfo = FindDevice(NULL,&Startup,&DosEnvec,&FlatNode -> fn_Name[1]))
{
struct IOExtTD *DiskRequest;
DB(kprintf("DevInfo: %08lx \n",FlatNode -> fn_DevInfo));
if(DiskRequest = (struct IOExtTD *)CreateExtIO(DiskPort,sizeof(struct IOExtTD)))
{
DB(kprintf("DiskRequest: %08lx \n",DiskRequest));
BtoCStr(NameBuffer,Startup -> fssm_Device,256);
if(!OpenDevice(NameBuffer,Startup -> fssm_Unit,DiskRequest,Startup -> fssm_Flags))
{
/* We are actually faking part of the data
* to be returned in the fileinfoblock.
* This isn't Unix and there are only two
* kinds of directory entries: files and
* directories. The protection bits are by
* default configured to mimic the state of
* the corresponding drive. If not write-
* enabled, the file will have the write
* access-bit cleared, if there is no disk
* in the drive, the read bit will be cleared,
* the file size will be zero as well.
*/
memset(FileInfo,0,sizeof(struct FileInfoBlock));
FileInfo -> fib_DiskKey = 0; // FileLock -> fl_Key;
FileInfo -> fib_DirEntryType = ST_FILE;
FileInfo -> fib_Protection = FIBF_EXECUTE|FIBF_DELETE;
FileInfo -> fib_Size = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces * (DosEnvec -> de_SizeBlock << 2);
FileInfo -> fib_NumBlocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
FileInfo -> fib_Date = CreationDate;
DB(kprintf("FileSize: %08lx \n",FileInfo ->fib_Size));
memcpy(FileInfo -> fib_FileName,BADDR(FlatNode -> fn_DevInfo -> dn_Name),((UBYTE *)BADDR(FlatNode -> fn_DevInfo -> dn_Name))[0] + 1);
DiskRequest -> iotd_Req . io_Command = TD_PROTSTATUS;
if(!DoIO(DiskRequest))
{
if(DiskRequest -> iotd_Req . io_Actual)
FileInfo -> fib_Protection |= FIBF_WRITE;
}
DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
if(!DoIO(DiskRequest))
{
if(DiskRequest -> iotd_Req . io_Actual)
{
FileInfo -> fib_Protection |= FIBF_READ|FIBF_WRITE;
FileInfo -> fib_Size = FileInfo -> fib_NumBlocks = 0;
}
}
Success = TRUE;
CloseDevice(DiskRequest);
}
DeleteExtIO(DiskRequest);
}
}
}
if(Success)
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
break;
case ACTION_CREATE_DIR:
DB(kprintf("ACTION_CREATE_DIR\n"));
ReturnPacket(FlatPacket,DOSFALSE,ERROR_DISK_FULL,HandlerProc);
break;
case ACTION_DELETE_OBJECT:
DB(kprintf("ACTION_DELETE_OBJECT\n"));
ReturnPacket(FlatPacket,DOSFALSE,ERROR_DELETE_PROTECTED,HandlerProc);
break;
case ACTION_RENAME_OBJECT:
case ACTION_SET_PROTECT:
case ACTION_SET_COMMENT:
case ACTION_SET_DATE:
DB(kprintf("ACTION_WUSEL\n"));
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_IN_USE,HandlerProc);
break;
/* Examine the next directory entry (if available). */
case ACTION_EXAMINE_NEXT:
DB(kprintf("ACTION_EXAMINE_NEXT\n"));
/* This works very much the same as above, with the
* exception that we are trying to gather information
* on the next available DosList Device entry.
*/
if((FileLock = (struct FileLock *)BADDR(FlatPacket -> dp_Arg1)) && (FileInfo = (struct FileInfoBlock *)BADDR(FlatPacket -> dp_Arg2)))
{
BYTE Success = FALSE;
if(FlatNode = FindFlatNodeByID(FileLock -> fl_Key))
{
struct FileSysStartupMsg *Startup;
struct DosEnvec *DosEnvec;
DB(kprintf("name \"%s\"\n",&FlatNode -> fn_Name[1]));
if(FlatNode -> fn_DevInfo = FindDevice(FlatNode -> fn_DevInfo,&Startup,&DosEnvec,NULL))
{
struct IOExtTD *DiskRequest;
if(DiskRequest = (struct IOExtTD *)CreateExtIO(DiskPort,sizeof(struct IOExtTD)))
{
BtoCStr(NameBuffer,Startup -> fssm_Device,256);
if(!OpenDevice(NameBuffer,Startup -> fssm_Unit,DiskRequest,Startup -> fssm_Flags))
{
memset(FileInfo,0,sizeof(struct FileInfoBlock));
FileInfo -> fib_DiskKey = FileLock -> fl_Key;
FileInfo -> fib_DirEntryType = ST_FILE;
FileInfo -> fib_Protection = FIBF_EXECUTE|FIBF_DELETE;
FileInfo -> fib_Size = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces * (DosEnvec -> de_SizeBlock << 2);
FileInfo -> fib_NumBlocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
FileInfo -> fib_Date = CreationDate;
memcpy(FileInfo -> fib_FileName,BADDR(FlatNode -> fn_DevInfo -> dn_Name),((UBYTE *)BADDR(FlatNode -> fn_DevInfo -> dn_Name))[0] + 1);
DiskRequest -> iotd_Req . io_Command = TD_PROTSTATUS;
if(!DoIO(DiskRequest))
{
if(DiskRequest -> iotd_Req . io_Actual)
FileInfo -> fib_Protection |= FIBF_WRITE;
}
DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
if(!DoIO(DiskRequest))
{
if(DiskRequest -> iotd_Req . io_Actual)
{
FileInfo -> fib_Protection |= FIBF_READ|FIBF_WRITE;
FileInfo -> fib_Size = FileInfo -> fib_NumBlocks = 0;
}
}
Success = TRUE;
CloseDevice(DiskRequest);
}
DeleteExtIO(DiskRequest);
}
}
else
{
ReturnPacket(FlatPacket,DOSFALSE,ERROR_NO_MORE_ENTRIES,HandlerProc);
break;
}
}
if(Success)
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
break;
/* Open any file for reading/writing. */
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT:
case ACTION_FINDUPDATE:
/* Convert the file name. */
BtoCStr(NameBuffer,FlatPacket -> dp_Arg3,256);
DB(kprintf("ACTION_FIND... \"%s\"\n",NameBuffer));
if(FileName = BaseName(NameBuffer))
{
LONG Mode;
DB(kprintf("base name \"%s\"\n",FileName));
/* Only the MODE_OLDFILE type allows
* shared data access.
*/
if(FlatPacket -> dp_Type == ACTION_FINDINPUT)
Mode = SHARED_LOCK;
else
Mode = EXCLUSIVE_LOCK;
FileHandle = (struct FileHandle *)BADDR(FlatPacket -> dp_Arg1);
/* Is there already a lock or filehandle by this
* name?
*/
if(FlatNode = FindFlatNodeByName(FileName))
{
/* If so, is it locked? */
if((FlatNode -> fn_Mode != Mode) || (Mode == EXCLUSIVE_LOCK && FlatNode -> fn_Mode == EXCLUSIVE_LOCK))
{
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_IN_USE,HandlerProc);
break;
}
else
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
}
/* Create a new list entry. */
if(FlatNode = CreateNode(DiskPort,Mode,FileName))
{
AddTail(&FlatList,(struct Node *)FlatNode);
FileHandle -> fh_Arg1 = FlatNode -> fn_UniqueID;
DB(kprintf("UniqueID %ld\n",FileHandle->fh_Arg1));
/* Turn on the disk motor. */
FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_MOTOR;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = 1;
DoIO(FlatNode -> fn_DiskRequest);
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_NO_FREE_STORE,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_NOT_FOUND,HandlerProc);
break;
/* Close a file opened above. */
case ACTION_END:
DB(kprintf("ACTION_END\n"));
/* Find the node. */
if(FlatNode = FindFlatNodeByID(FlatPacket -> dp_Arg1))
{
/* Turn off the motor. */
FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_MOTOR;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = 0;
DoIO(FlatNode -> fn_DiskRequest);
Remove((struct Node *)FlatNode);
DeleteNode(FlatNode);
}
ReturnPacket(FlatPacket,DOSTRUE,NULL,HandlerProc);
break;
/* Read a couple of bytes from a file. */
case ACTION_READ:
DB(kprintf("ACTION_READ\n"));
/* Do we have a valid filehandle? */
if(FlatNode = FindFlatNodeByID(FlatPacket -> dp_Arg1))
{
LONG Res1,Res2 = NULL;
ReadBytes = FlatPacket -> dp_Arg3;
/* Reading across the data media size? */
if(FlatNode -> fn_Position + ReadBytes > (FlatNode -> fn_BlockSize * FlatNode -> fn_NumBlocks))
{
if((ReadBytes = FlatNode -> fn_BlockSize * FlatNode -> fn_NumBlocks - FlatNode -> fn_Position) < 0)
{
ReadBytes = -1;
Res2 = ERROR_SEEK_ERROR;
}
}
/* Read a few bytes. */
if(ReadBytes > 0)
{
if((Bytes = DoRead(FlatNode,&Res2,ReadBytes,(APTR)FlatPacket -> dp_Arg2,FlatPacket -> dp_Port -> mp_SigTask)) > 0)
FlatNode -> fn_Position += Bytes;
Res1 = Bytes;
}
else
Res1 = 0;
ReturnPacket(FlatPacket,Res1,Res2,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_WRONG_TYPE,HandlerProc);
break;
/* Write a few bytes to a file. */
case ACTION_WRITE:
DB(kprintf("ACTION_WRITE\n"));
if(FlatNode = FindFlatNodeByID(FlatPacket -> dp_Arg1))
{
LONG Res1,Res2 = NULL;
WriteBytes = FlatPacket -> dp_Arg3;
if(FlatNode -> fn_Position + WriteBytes > (FlatNode -> fn_BlockSize * FlatNode -> fn_NumBlocks))
{
if((WriteBytes = FlatNode -> fn_BlockSize * FlatNode -> fn_NumBlocks - FlatNode -> fn_Position) < 0)
{
WriteBytes = -1;
Res2 = ERROR_DISK_FULL;
}
}
if(WriteBytes > 0)
{
if((Bytes = DoWrite(FlatNode,&Res2,WriteBytes,(APTR)FlatPacket -> dp_Arg2,FlatPacket -> dp_Port -> mp_SigTask)) > 0)
FlatNode -> fn_Position += Bytes;
Res1 = Bytes;
}
else
Res1 = 0;
ReturnPacket(FlatPacket,Res1,Res2,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_WRONG_TYPE,HandlerProc);
break;
/* Move the r/w pointer inside a file. */
case ACTION_SEEK:
DB(kprintf("ACTION_SEEK\n"));
if(FlatNode = FindFlatNodeByID(FlatPacket -> dp_Arg1))
{
LONG Res1,Res2 = NULL;
if(FlatPacket -> dp_Arg3 == OFFSET_BEGINNING)
NewPosition = FlatPacket -> dp_Arg2;
if(FlatPacket -> dp_Arg3 == OFFSET_CURRENT)
NewPosition = FlatNode -> fn_Position + FlatPacket -> dp_Arg2;
if(FlatPacket -> dp_Arg3 == OFFSET_END)
NewPosition = (FlatNode -> fn_BlockSize * FlatNode -> fn_NumBlocks) - FlatPacket -> dp_Arg2;
if(NewPosition < 0 || NewPosition > (FlatNode -> fn_BlockSize * FlatNode -> fn_NumBlocks))
{
Res1 = -1;
Res2 = ERROR_SEEK_ERROR;
}
else
{
Res1 = FlatNode -> fn_Position;
FlatNode -> fn_Position = NewPosition;
}
ReturnPacket(FlatPacket,Res1,Res2,HandlerProc);
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_WRONG_TYPE,HandlerProc);
break;
/* Remove the handler. */
case ACTION_DIE:
DB(kprintf("ACTION_DIE\n"));
/* Are we allowed to remove ourselves? */
if(!FlatList . lh_Head -> ln_Succ)
{
ReturnPacket(FlatPacket,DOSTRUE,0,HandlerProc);
goto FallOff;
}
else
ReturnPacket(FlatPacket,DOSFALSE,ERROR_OBJECT_IN_USE,HandlerProc);
break;
/* Ignore the rest of the packets. */
default:
DB(kprintf("dp_Type %ld\n",FlatPacket -> dp_Type));
DB(kprintf("dp_Arg1 0x%08lx\n",FlatPacket -> dp_Arg1));
DB(kprintf("dp_Arg2 0x%08lx\n",FlatPacket -> dp_Arg2));
DB(kprintf("dp_Arg3 0x%08lx\n",FlatPacket -> dp_Arg3));
DB(kprintf("dp_Arg4 0x%08lx\n",FlatPacket -> dp_Arg4));
DB(kprintf("dp_Arg5 0x%08lx\n",FlatPacket -> dp_Arg5));
DB(kprintf("dp_Arg6 0x%08lx\n",FlatPacket -> dp_Arg6));
DB(kprintf("dp_Arg7 0x%08lx\n",FlatPacket -> dp_Arg7));
ReturnPacket(FlatPacket,DOSFALSE,ERROR_ACTION_NOT_KNOWN,HandlerProc);
break;
}
DB(kprintf("\n"));
}
/* Cease actions, close libraries and exit. */
FallOff: Forbid();
if(VolumeNode)
{
struct DosInfo *DosInfo;
struct DeviceNode *DevNode;
DosInfo = (struct DosInfo *)(((struct RootNode *)DOSBase -> dl_Root) -> rn_Info);
DevNode = (struct DeviceNode *)(BADDR(DosInfo -> di_DevInfo));
while(DevNode)
{
if(DevNode -> dn_Next = MKBADDR(VolumeNode))
{
DevNode -> dn_Next = VolumeNode -> dl_Next;
break;
}
else
DevNode = (struct DeviceNode *)BADDR(DevNode -> dn_Next);
}
VolumeNode -> dl_Task = NULL;
VolumeNode -> dl_DiskType = ID_NO_DISK_PRESENT;
}
FlatDevNode -> dn_Task = NULL;
if(FlatDevNode -> dn_SegList)
{
UnLoadSeg(FlatDevNode -> dn_SegList);
FlatDevNode -> dn_SegList = NULL;
}
if(DiskPort)
DeletePort(DiskPort);
if(IntuitionBase)
CloseLibrary(IntuitionBase);
if(DOSBase)
CloseLibrary(DOSBase);
return(0);
}
else
return(RETURN_FAIL);
}
/* BaseName(UBYTE *String):
*
* Returns the base of a filename.
*/
UBYTE * __regargs
BaseName(UBYTE *String)
{
if(String[0])
{
WORD i;
for(i = strlen(String) - 1 ; i >= 0 ; i--)
{
if(String[i] == ':' || String[i] == '/')
{
if(String[i + 1])
return(&String[i + 1]);
else
return(NULL);
}
}
return(String);
}
else
return(NULL);
}
/* Local2Upper(UBYTE c):
*
* Convert a character to upper case.
*/
UBYTE __regargs
Local2Upper(UBYTE c)
{
return((UBYTE)((((c) >= 224 && (c) <= 254) || ((c) >= 'a' && (c) <= 'z')) ? (c) - 32 : c));
}
/* StrCmp(UBYTE *a,UBYTE *b):
*
* Do string comparison ignoring case.
*/
UBYTE __regargs
StrCmp(UBYTE *a,UBYTE *b)
{
LONG Len = strlen(a);
if(Len != strlen(b))
return(1);
else
{
if(Len)
{
do
{
if(Local2Upper(*a++) != Local2Upper(*b++))
return(1);
}
while(--Len);
}
return(0);
}
}
/* FindFlatNodeByID(ULONG UniqueID):
*
* Scan the item list looking for a list entry with
* a matching ID.
*/
struct FlatNode * __regargs
FindFlatNodeByID(ULONG UniqueID)
{
struct FlatNode *Node;
Node = (struct FlatNode *)FlatList . lh_Head;
while(Node -> fn_Succ)
{
if(Node -> fn_UniqueID == UniqueID)
return(Node);
Node = Node -> fn_Succ;
}
return(NULL);
}
/* FindFlatNodeByName(UBYTE *Name):
*
* Scan the item list looking for an entry with a
* matching name.
*/
struct FlatNode * __regargs
FindFlatNodeByName(UBYTE *Name)
{
struct FlatNode *Node;
for(Node = (struct FlatNode *)FlatList . lh_Head ; Node -> fn_Succ ; Node = Node -> fn_Succ)
{
if(!StrCmp(&Node -> fn_Name[1],Name))
return(Node);
}
return(NULL);
}
/* BtoCStr(UBYTE *Name,BSTR String,LONG MaxLength):
*
* Convert a BCPL string into a `C' string.
*/
VOID __regargs
BtoCStr(UBYTE *Name,BSTR String,LONG MaxLength)
{
UBYTE *Src,Length;
if(Src = (UBYTE *)BADDR(String))
{
if((Length = Src[0]) > MaxLength)
Length = MaxLength;
Src++;
while(Length--)
*Name++ = *Src++;
*Name = 0;
}
}
/* ShowRequest(APTR WindowPtr,BYTE Type,UBYTE *Drive):
*
* If trouble shows up, behave like the standard
* FS and complain.
*/
LONG __regargs
ShowRequest(APTR WindowPtr,BYTE Type,UBYTE *Drive)
{
STATIC struct IntuiText DiskWriteProtected[3] =
{
{0,1,JAM2,15, 5,NULL,"Disk in drive", &DiskWriteProtected[1]},
{0,1,JAM2,15,15,NULL,"################################", &DiskWriteProtected[2]},
{0,1,JAM2,15,25,NULL,"is write protected", NULL}
};
STATIC struct IntuiText DiskNotPresent[2] =
{
{0,1,JAM2,15, 5,NULL,"No disk present in drive", &DiskNotPresent[1]},
{0,1,JAM2,15,15,NULL,"################################", NULL}
};
STATIC struct IntuiText DiskUnreadable[3] =
{
{0,1,JAM2,15, 5,NULL,"Disk in drive", &DiskUnreadable[1]},
{0,1,JAM2,15,15,NULL,"################################", &DiskUnreadable[2]},
{0,1,JAM2,15,25,NULL,"is unreadable", NULL}
};
STATIC struct IntuiText DiskWriteError[2] =
{
{0,1,JAM2,15, 5,NULL,"Error writing to drive", &DiskWriteError[1]},
{0,1,JAM2,15,15,NULL,"################################", NULL}
};
STATIC struct IntuiText Retry =
{
0,1,JAM2,7,3,NULL,"Retry",NULL
};
STATIC struct IntuiText Cancel =
{
0,1,JAM2,7,3,NULL,"Cancel",NULL
};
/* A -1 will result in cancelling the
* requester.
*/
if(WindowPtr != (APTR)-1)
{
struct IntuiText *BodyText;
WORD i;
/* Install the right alert type. */
switch(Type)
{
case ERR_WRITEPROTECT: BodyText = DiskWriteProtected;
break;
case ERR_NODISK: BodyText = DiskNotPresent;
break;
case ERR_UNREADABLE: BodyText = DiskUnreadable;
break;
case ERR_WRITEERROR: BodyText = DiskWriteError;
break;
}
/* Add the drive name. */
for(i = 0 ; BodyText[1] . IText[i] = Local2Upper(Drive[i + 1]) ; i++);
/* Show the requester. */
return((LONG)AutoRequest(WindowPtr,BodyText,&Retry,&Cancel,DISKINSERTED,NULL,320,72));
}
return(FALSE);
}
/* FindDevice():
*
* Find a DeviceNode entry in the DosList.
*/
struct DeviceNode * __regargs
FindDevice(struct DeviceNode *LastNode,struct FileSysStartupMsg **Startup,struct DosEnvec **DosEnvec,UBYTE *Name)
{
struct DeviceNode *DevInfo;
STATIC UBYTE NameBuffer[257];
Forbid();
if(LastNode)
DevInfo = (struct DeviceNode *)BADDR(LastNode -> dn_Next);
else
DevInfo = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct RootNode *)DOSBase -> dl_Root) -> rn_Info)) -> di_DevInfo);
while(DevInfo)
{
if(DevInfo -> dn_Type == DLT_DEVICE && DevInfo -> dn_Task && DevInfo -> dn_Startup)
{
if(TypeOfMem(DevInfo -> dn_Task) && TypeOfMem(BADDR(DevInfo -> dn_Startup)))
{
struct DosEnvec *Environ = (struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(DevInfo -> dn_Startup)) -> fssm_Environ);
if(TypeOfMem(Environ))
{
if(Name)
{
BtoCStr(NameBuffer,DevInfo -> dn_Name,256);
if(!StrCmp(NameBuffer,Name))
{
if(Startup)
*Startup = (struct FileSysStartupMsg *)BADDR(DevInfo -> dn_Startup);
if(DosEnvec)
*DosEnvec = Environ;
Permit();
return(DevInfo);
}
}
else
{
if(Startup)
*Startup = (struct FileSysStartupMsg *)BADDR(DevInfo -> dn_Startup);
if(DosEnvec)
*DosEnvec = Environ;
Permit();
return(DevInfo);
}
}
}
}
DevInfo = (struct DeviceNode *)BADDR(DevInfo -> dn_Next);
}
Permit();
return(NULL);
}
/* DeleteNode(struct FlatNode *FlatNode):
*
* Delete a freshly created item node freeing
* all associated resources.
*/
VOID __regargs
DeleteNode(struct FlatNode *FlatNode)
{
if(FlatNode -> fn_DiskBuffer)
FreeMem(FlatNode -> fn_DiskBuffer,FlatNode -> fn_BlockSize);
if(FlatNode -> fn_DiskRequest)
{
if(FlatNode -> fn_DiskRequest -> iotd_Req . io_Device)
{
FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = CMD_UPDATE;
DoIO(FlatNode -> fn_DiskRequest);
FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_MOTOR;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = 0;
DoIO(FlatNode -> fn_DiskRequest);
CloseDevice(FlatNode -> fn_DiskRequest);
}
DeleteExtIO(FlatNode -> fn_DiskRequest);
}
FreeMem(FlatNode,sizeof(struct FlatNode));
}
/* CreateNode(struct MsgPort *DiskPort,LONG Type,UBYTE *Name):
*
* Create an item node with given characteristics,
* can be either shared or exclusive access, if a name
* is given will open the approriate device driver.
*/
struct FlatNode * __regargs
CreateNode(struct MsgPort *DiskPort,LONG Type,UBYTE *Name)
{
struct FlatNode *FlatNode;
if(FlatNode = (struct FlatNode *)AllocMem(sizeof(struct FlatNode),MEMF_PUBLIC|MEMF_CLEAR))
{
if(Name)
{
struct DeviceNode *DevInfo;
struct FileSysStartupMsg *Startup;
struct DosEnvec *DosEnvec;
/* Try to find the device. */
if(!(DevInfo = FindDevice(NULL,&Startup,&DosEnvec,Name)))
{
DeleteNode(FlatNode);
return(NULL);
}
/* Create a device request. */
if(!(FlatNode -> fn_DiskRequest = (struct IOExtTD *)CreateExtIO(DiskPort,sizeof(struct IOExtTD))))
{
DeleteNode(FlatNode);
return(NULL);
}
/* Open the device driver. */
if(OpenDevice(&((UBYTE *)BADDR(Startup -> fssm_Device))[1],Startup -> fssm_Unit,FlatNode -> fn_DiskRequest,Startup -> fssm_Flags))
{
DeleteNode(FlatNode);
return(NULL);
}
/* Inquire the unit data. */
FlatNode -> fn_BlockSize = DosEnvec -> de_SizeBlock << 2;
FlatNode -> fn_FirstBlock = DosEnvec -> de_LowCyl * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
FlatNode -> fn_NumBlocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
/* Create a r/w buffer. */
if(!(FlatNode -> fn_DiskBuffer = (APTR)AllocMem(FlatNode -> fn_BlockSize,DosEnvec -> de_BufMemType)))
{
DeleteNode(FlatNode);
return(NULL);
}
strcpy(&FlatNode -> fn_Name[1],Name);
}
FlatNode -> fn_Mode = Type;
FlatNode -> fn_UniqueID = UniqueCounter++;
}
return(FlatNode);
}
/* ReturnPacket():
*
* Return a standard DOS packet to its sender.
*/
VOID __regargs
ReturnPacket(struct DosPacket *Packet,ULONG Res1,ULONG Res2,struct Process *HandlerProc)
{
struct MsgPort *ReplyPort;
DB(kprintf("Return: %lx,%lx\n",Res1,Res2));
ReplyPort = Packet -> dp_Port;
Packet -> dp_Res1 = Res1;
Packet -> dp_Res2 = Res2;
Packet -> dp_Port = &HandlerProc -> pr_MsgPort;
Packet -> dp_Link -> mn_Node . ln_Name = (APTR)Packet;
Packet -> dp_Link -> mn_Node . ln_Succ = NULL;
Packet -> dp_Link -> mn_Node . ln_Pred = NULL;
PutMsg(ReplyPort,Packet -> dp_Link);
}
/* WaitPacket(struct Process *HandlerProc):
*
* Wait for packet arrival.
*/
struct DosPacket * __regargs
WaitPacket(struct Process *HandlerProc)
{
struct Message *DOSMsg;
WaitPort(&HandlerProc -> pr_MsgPort);
DOSMsg = (struct Message *)GetMsg(&HandlerProc -> pr_MsgPort);
return((struct DosPacket *)DOSMsg -> mn_Node . ln_Name);
}
/* DoRead():
*
* Read a few bytes from a file.
*/
LONG __regargs
DoRead(struct FlatNode *FlatNode,LONG *Error,LONG Size,UBYTE *Buffer,struct Process *Caller)
{
LONG Block,Length,BytesRead = 0,Offset = FlatNode -> fn_Position;
UBYTE *DiskBuffer = FlatNode -> fn_DiskBuffer;
/* Time for a check? */
if(!FlatNode -> fn_CheckCount)
{
FOREVER
{
FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
/* Is there still a disk in the drive? */
if(!DoIO(FlatNode -> fn_DiskRequest))
{
if(FlatNode -> fn_DiskRequest -> iotd_Req . io_Actual)
{
if(!ShowRequest(Caller -> pr_WindowPtr,ERR_NODISK,&FlatNode -> fn_Name[1]))
{
*Error = ERROR_NO_DISK;
return(0);
}
}
else
break;
}
}
}
if(FlatNode -> fn_CheckCount++ == 10)
FlatNode -> fn_CheckCount = 0;
/* Convert offset from bytes into blocks. */
Block = Offset / FlatNode -> fn_BlockSize;
Offset = Offset % FlatNode -> fn_BlockSize;
if(Size > 0)
{
/* Read the data block by block... */
while(Size > 0)
{
Retry: FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = CMD_READ;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Offset = Block * FlatNode -> fn_BlockSize + FlatNode -> fn_FirstBlock * FlatNode -> fn_BlockSize;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = FlatNode -> fn_BlockSize;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Data = DiskBuffer;
/* Read the block. */
if(DoIO(FlatNode -> fn_DiskRequest))
{
if(ShowRequest(Caller -> pr_WindowPtr,ERR_UNREADABLE,&FlatNode -> fn_Name[1]))
goto Retry;
else
{
*Error = FlatNode -> fn_DiskRequest -> iotd_Req . io_Error;
return(BytesRead);
}
}
Length = FlatNode -> fn_BlockSize - Offset;
if(Length > Size)
Length = Size;
/* Copy the data. */
memcpy(Buffer,&DiskBuffer[Offset],Length);
Buffer = &Buffer[Length];
Size -= Length;
BytesRead += Length;
Block++;
Offset = 0;
}
}
return(BytesRead);
}
/* DoWrite():
*
* Write a few bytes to a file.
*/
LONG __regargs
DoWrite(struct FlatNode *FlatNode,LONG *Error,LONG Size,UBYTE *Buffer,struct Process *Caller)
{
LONG Block,Length,BytesWritten = 0,Offset = FlatNode -> fn_Position;
UBYTE *DiskBuffer = FlatNode -> fn_DiskBuffer;
/* Time for a check? */
if(!FlatNode -> fn_CheckCount)
{
FOREVER
{
FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
/* Is there a disk in the drive? */
if(!DoIO(FlatNode -> fn_DiskRequest))
{
if(FlatNode -> fn_DiskRequest -> iotd_Req . io_Actual)
{
if(!ShowRequest(Caller -> pr_WindowPtr,ERR_NODISK,&FlatNode -> fn_Name[1]))
{
*Error = ERROR_NO_DISK;
return(0);
}
}
else
break;
}
}
FOREVER
{
FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = TD_PROTSTATUS;
/* Is the disk write enabled? */
if(!DoIO(FlatNode -> fn_DiskRequest))
{
if(FlatNode -> fn_DiskRequest -> iotd_Req . io_Actual)
{
if(!ShowRequest(Caller -> pr_WindowPtr,ERR_WRITEPROTECT,&FlatNode -> fn_Name[1]))
{
*Error = ERROR_DISK_WRITE_PROTECTED;
return(0);
}
}
else
break;
}
}
}
if(FlatNode -> fn_CheckCount++ == 10)
FlatNode -> fn_CheckCount = 0;
/* Convert offset from bytes into blocks. */
Block = Offset / FlatNode -> fn_BlockSize;
Offset = Offset % FlatNode -> fn_BlockSize;
if(Size > 0)
{
while(Size > 0)
{
Retry1: if(Offset)
{
/* The data to write is smaller
* than a block, so we'll have to
* read the block to write to first,
* copy the data over and write the
* block back.
*/
FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = CMD_READ;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Offset = Block * FlatNode -> fn_BlockSize + FlatNode -> fn_FirstBlock * FlatNode -> fn_BlockSize;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = FlatNode -> fn_BlockSize;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Data = DiskBuffer;
if(DoIO(FlatNode -> fn_DiskRequest))
{
if(ShowRequest(Caller -> pr_WindowPtr,ERR_UNREADABLE,&FlatNode -> fn_Name[1]))
goto Retry1;
else
{
*Error = FlatNode -> fn_DiskRequest -> iotd_Req . io_Error;
return(BytesWritten);
}
}
Length = FlatNode -> fn_BlockSize - Offset;
if(Length > Size)
Length = Size;
memcpy(&DiskBuffer[Offset],Buffer,Length);
Retry2: FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = CMD_WRITE;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Offset = Block * FlatNode -> fn_BlockSize + FlatNode -> fn_FirstBlock * FlatNode -> fn_BlockSize;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = FlatNode -> fn_BlockSize;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Data = DiskBuffer;
if(DoIO(FlatNode -> fn_DiskRequest))
{
if(ShowRequest(Caller -> pr_WindowPtr,ERR_WRITEERROR,&FlatNode -> fn_Name[1]))
goto Retry2;
else
{
*Error = FlatNode -> fn_DiskRequest -> iotd_Req . io_Error;
return(BytesWritten);
}
}
Buffer = &Buffer[Length];
Size -= Length;
BytesWritten += Length;
Block++;
Offset = 0;
}
else
{
if(Size > FlatNode -> fn_BlockSize)
Length = FlatNode -> fn_BlockSize;
else
{
if(Size < FlatNode -> fn_BlockSize)
memset(DiskBuffer,0,FlatNode -> fn_BlockSize);
Length = Size;
}
memcpy(DiskBuffer,Buffer,Length);
Retry3: FlatNode -> fn_DiskRequest -> iotd_Req . io_Command = CMD_WRITE;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Offset = Block * FlatNode -> fn_BlockSize + FlatNode -> fn_FirstBlock * FlatNode -> fn_BlockSize;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Length = FlatNode -> fn_BlockSize;
FlatNode -> fn_DiskRequest -> iotd_Req . io_Data = DiskBuffer;
if(DoIO(FlatNode -> fn_DiskRequest))
{
if(ShowRequest(Caller -> pr_WindowPtr,ERR_WRITEERROR,&FlatNode -> fn_Name[1]))
goto Retry1;
else
{
*Error = FlatNode -> fn_DiskRequest -> iotd_Req . io_Error;
return(BytesWritten);
}
}
Buffer = &Buffer[Length];
Size -= Length;
BytesWritten += Length;
Block++;
}
}
}
return(BytesWritten);
}